#include "parser.h"
#include "iostream"
#include <QtNetwork/QtNetwork>
#include <QTextCodec>
#include "tnotify.h"
#include "singleton.h"
#include "tthreadlist.h"
#include "tthreadlistitem.h"
#include "ttestwindow.h"

parser::parser(QWidget *parent) :
    QWidget(parent),
    url(new QLineEdit()),
    addButton (new QPushButton("Add Thread", this)),
    deleteButton (new QPushButton("Delete Thread", this)),
    startAllButton (new QPushButton("Start All", this)),
    startButton (new QPushButton("Start", this)),
    ondemandButton(new QPushButton("On Demand")),
    stopButton (new QPushButton("Stop", this)),
    testButton (new QPushButton("Notify test", this)),
    hideButton (new QPushButton("Hide", this)),
    exitButton (new QPushButton("Exit", this)),
    listView (new TThreadList()),
    grid (new QGridLayout(this)),
    nm (&Singleton<TNetworkManager>::Instance()),
    notifications (&Singleton<TNotify>::Instance()),
    notificationNum(0),
    trayIcon (new QSystemTrayIcon()),
    trayIconMenu (new QMenu(this))
{
    std::cout << "Loading 1.1" << std::endl;
    grid->addWidget(url, 1,1);
    grid->addWidget(addButton, 1,2);
    url->setPlaceholderText("Type here thread URL");
    grid->addWidget(startAllButton, 2,2);
    grid->addWidget(startButton, 3,2);
    //grid->addWidget(ondemandButton, 4,2);
    ondemandButton->setDisabled(true);
    grid->addWidget(stopButton, 4,2);
    //stopButton->setEnabled(false);
    grid->addWidget(testButton, 5,2);
    grid->addWidget(deleteButton, 6,2);
    grid->addWidget(hideButton, 7,2);
    grid->addWidget(exitButton, 8,2);
    grid->addWidget(listView, 2,1,9,1);
    std::cout << "Loading 1.2" << std::endl;
    QSettings settings;
    settings.beginGroup("Parser");
    if (settings.contains("hanabira")){
	QList<QNetworkCookie> cookieList;
	cookieList.append(QNetworkCookie("hanabira", settings.value("hanabira").toByteArray()));
	nm->cookieJar()->setCookiesFromUrl(cookieList, QUrl(QString("http://dobrochan.ru")));
    }else{
	QNetworkReply* rep = nm->get2(QNetworkRequest(QUrl(QString("http://dobrochan.ru/api/user.json"))));
	QEventLoop loops;
	QObject::connect(rep, SIGNAL(finished()), &loops, SLOT(quit()));
	loops.exec();
	settings.setValue("hanabira", nm->cookieJar()->cookiesForUrl(QUrl(QString("http://dobrochan.ru"))).at(0).value());
    }
    settings.endGroup();

    settings.beginGroup("Urls");
    QStringList savedUrls;
    QStringList savedUrlsNames;
    if (settings.contains("UrlsList")){
        savedUrls = settings.value("UrlsList").toStringList();
    }
    if (settings.contains("UrlsNamesList")){
        savedUrlsNames = settings.value("UrlsNamesList").toStringList();
	std::cout << savedUrlsNames.at(0).toStdString() << std::endl;
    }
    settings.endGroup();
    std::cout << "Loading 1.3" << std::endl;
    if (!savedUrls.isEmpty()){
        for (int i=0; i< savedUrls.count(); i++){
            if (!savedUrlsNames.isEmpty()){
                listView->addThread(QUrl(savedUrls.at(i)), savedUrlsNames.at(i));
		std::cout << savedUrls.at(i).toStdString() << " - " << savedUrlsNames.at(i).toStdString() <<std::endl;
            }else{
                listView->addThread(QUrl(savedUrls.at(i)), NULL);
            }
        }
    }

    std::cout << "Loading 1.x" << std::endl;
    this->setLayout(grid);
    listView->setFocus();
    QObject::connect(addButton, SIGNAL(clicked()), this, SLOT(addURL()));
    QObject::connect(url, SIGNAL(returnPressed()), this, SLOT(addURL()));
    QObject::connect(deleteButton, SIGNAL(clicked()), this, SLOT(deleteURL()));
    QObject::connect(startButton, SIGNAL(clicked()), this, SLOT(start()));
    QObject::connect(startAllButton, SIGNAL(clicked()), this, SLOT(startAll()));
    QObject::connect(stopButton, SIGNAL(clicked()), this, SLOT(stop()));
    QObject::connect(testButton, SIGNAL(clicked()), this, SLOT(test()));
    QObject::connect(hideButton, SIGNAL(clicked()), this, SLOT(close()));
    QObject::connect(exitButton, SIGNAL(clicked()), qApp, SLOT(quit()));

    this->resize(600,250);

    if(QSystemTrayIcon::isSystemTrayAvailable()){
        std::cout << "Showing tray icon.." << std::endl;
        trayIcon->setIcon(QIcon(":/images/favicon.png"));
        connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
                this, SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason)));
        trayIconMenu->addAction("Exit");
        QObject::connect(trayIconMenu->actions().at(0), SIGNAL(triggered()), qApp, SLOT(quit()));
        trayIcon->show();
    }else{
        std::cout << "No tray icon available." << std::endl;
    }
    for(int i = 0; i < this->dynamicPropertyNames().count(); i++){
        std::cout << QString(this->dynamicPropertyNames().at(i)).toStdString() << std::endl;
    }
}

void parser::addURL(void){
    //QRegExp* regexp = new QRegExp(QString("(http://dobrochan.ru/[lor|b]/res/[0-9]*.xhtml)"));
    QRegExp* regexp = new QRegExp(QString("(http://dobrochan.ru/(mad|lor|b|vg)/res/([0-9]*).xhtml)"));
    if(QUrl(url->text()).isValid() and regexp->indexIn(url->text()) != -1){
        std::cout<< "Echo 1" << std::endl;
        listView->addThread(QUrl(regexp->cap(1)), NULL);
        url->clear();
        std::cout<< "Echo End"<<std::endl;
    }else{
        QMessageBox* msgBox = new QMessageBox();
        msgBox->setText("Invalid URL is specified");
        msgBox->show();
    }
}

void parser::deleteURL(void){
    for(int i=listView->topLevelItemCount()-1; i>= 0; i--){
      if(listView->topLevelItem(i)->isSelected()){
          //std::cout << "Deleting thread: " << urlList.at(i)->getName().toStdString() << std::endl;
          listView->deleteThread(i);
      }
    }
}

void parser::start(void){
    if (!listView->selectedItems().isEmpty()){
        listView->startWatch(listView->currentIndex().row());
    }
}

void parser::startAll(void){
    for(int i=0; i < listView->topLevelItemCount(); i++){
        listView->startWatch(i);
    }
}

void parser::stop(){
    if (!listView->selectedItems().isEmpty()){
        listView->stopWatch(listView->currentIndex().row());
    }
}

QString parser::getTitleFromReply(QString data){
    QRegExp expTitle("\"title\":\\s\"([^\"]*)\"");
    expTitle.indexIn(data);
    QString title = expTitle.cap(1);
    return toUnicode(expTitle.cap(1));
}

QString parser::getMessageFromReply(QString data){
    QRegExp messageExp("\"message\":\\s\"([^\"]*)\"");
    messageExp.indexIn(data);
    QString tmp(messageExp.cap(1));
    tmp = parser::toUnicode(tmp);
    return tmp;
}


QString parser::toUnicode (QString str){
    QRegExp newLine("\\\\r\\\\n");
    str.replace(newLine, "\n");
    QRegExp uni("\\\\u[0-9a-f]{4}");
    int pos = 0;
    while ((pos = uni.indexIn(str, pos)) != -1) {
        str.replace(pos++, 6, QChar(uni.cap(0).right(4).toUShort(0, 16)));
    }
    return str;
}

void parser::test(void){
    TTestWindow* testWindow =  &Singleton<TTestWindow>::Instance();
    testWindow->show();
}


void parser::addNotify(void){
    notificationNum++;
}

void parser::deleteNotify(void){
    if(notificationNum > 0){
        notificationNum--;
    }else{
        std::cout << "Sorry, but current notification number is zero" << std::endl;
    }
}

void parser::closeEvent(QCloseEvent *event)
 {
     if (trayIcon->isVisible()) {
         notifications->newNotify("Dobrochan Parser", "See you soon.\nI'm in tray now.");\
         hide();
         event->ignore();
     }
 }

void parser::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
 {
    std::cout << reason << std::endl;
     switch (reason) {
     case QSystemTrayIcon::Context:
         showTrayIconMenu();
         break;
     case QSystemTrayIcon::Trigger:
         break;
     case QSystemTrayIcon::DoubleClick:
         if (this->isMinimized()){
             this->showNormal();
         }else{
             this->show();
         }
         break;
     default:
         ;
     }
 }

void parser::showTrayIconMenu(void){
    trayIconMenu->move(QCursor::pos().x(), QCursor::pos().y() - trayIconMenu->height());
    trayIconMenu->show();
}

void parser::changeEvent(QEvent *event){
    if (this->isMinimized()){
        this->close();
    }
    std::cout << event->type() << std::endl;
}
